package org.dce.screencapturer.objects;

import java.awt.AWTEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;

import org.dce.screencapturer.Drawing;

@SuppressWarnings("serial")
public abstract class DrawingObject 
	extends JComponent{

	protected DrawingObject(){
		setOpaque(false);
		setFocusable(true);
		enableEvents(
			AWTEvent.MOUSE_EVENT_MASK
			|AWTEvent.MOUSE_MOTION_EVENT_MASK
			|AWTEvent.FOCUS_EVENT_MASK);
	}
	
	private boolean insertionInProgress = false;
	private Point insertionFirstPoint;
	private Point insertionSecondPoint;
	
	private static final Insets INSETS = new Insets(0,0,0,0);
	
	public Insets getInsets(){
		return INSETS;
	}
	
	public Insets getInsets(Insets insets){
		insets.set(INSETS.top, INSETS.left, INSETS.bottom, INSETS.right);
		return insets;
	}

	public boolean intersects(Rectangle rectangle) {
		return super.getBounds().intersects(rectangle);
	}
	
	@Override
	protected void processMouseEvent(MouseEvent e) {
		
		if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getButton() == MouseEvent.BUTTON1){
			requestFocus();
		} 	
		super.processMouseEvent(e);
	}

	@Override
	protected void processFocusEvent(FocusEvent e) {
		repaint();
		super.processFocusEvent(e);
	}

	protected void paintComponent(Graphics g){
		
		Graphics2D g2d = (Graphics2D)g;
		
		draw(g2d);
		
	}
	
	public Drawing getArea(){
		return (Drawing)getParent();
	}
	
	protected boolean isSelected(){
		Drawing parent = getArea();
		
		return parent != null
			? parent.getSelectionHandler().isSelected(this)
			: false;
	}

	protected void firePropertyChange(String propertyName,Object oldValue,Object newValue){
		super.firePropertyChange(propertyName, oldValue, newValue);
	}
	
	protected Point getInsertionFirstPoint(){
		return insertionFirstPoint;
	}

	protected Point getTranslatedInsertionFirstPoint(){
		Point firstPoint = new Point(insertionFirstPoint);
		firstPoint.x-=getX();
		firstPoint.y-=getY();
		return firstPoint;
	}
	
	protected void setInsertionSecondPoint(Point secondPoint) {
		this.insertionSecondPoint = secondPoint;
	}

	protected Point getInsertionSecondPoint(){
		return insertionSecondPoint;
	}

	public Point getTranslatedInsertionSecondPoint(){
		return new Point(insertionSecondPoint.x - getX(), insertionSecondPoint.y - getY());
	}
	
	public abstract void draw(Graphics2D g);
	
	public boolean canDrag(MouseEvent e) {
		return true;
	}

	public final void insertionStarted(Point firstPoint) {
		insertionInProgress = true;
		insertionFirstPoint = firstPoint;
		onInsertionStarted();
	}

	public final void updateInsertionProgress(Point secondPoint) {
		this.insertionSecondPoint = secondPoint;
		onInsertionProgress();
	}

	public final void insertionDone(Point secondPoint) {
		this.insertionSecondPoint = secondPoint;
		insertionInProgress = false;
		onInsertionDone();
	}
	
	protected Rectangle getBounds(Point p1,Point p2){
		
		int x1 = Math.min(p1.x, p2.x);
		int y1 = Math.min(p1.y, p2.y);
		
		int x2 = Math.max(p1.x, p2.x);
		int y2 = Math.max(p1.y, p2.y);
		
		return new Rectangle(x1,y1,x2-x1,y2-y1);
	}

	protected boolean isInsertionInProgress(){
		return insertionInProgress;
	}

	protected void onInsertionStarted(){
		
	}
	
	protected void onInsertionProgress(){
		setBounds(getBounds(insertionFirstPoint,insertionSecondPoint));
	}

	protected void onInsertionDone(){
		setBounds(getBounds(insertionFirstPoint,insertionSecondPoint));
	}
}
